package com.sharesrc.jdev.wiimotedemo;

import java.util.Vector;

import org.wiigee.event.AccelerationEvent;
import org.wiigee.event.ActionStartEvent;
import org.wiigee.event.ActionStopEvent;
import org.wiigee.logic.Classifier;
import org.wiigee.logic.Gesture;
import org.wiigee.logic.GestureModel;
import org.wiigee.logic.TriggeredProcessingUnit;

import com.sharesrc.jdev.wiimotedemo.common.constant.Constants;
import com.sharesrc.jdev.wiimotedemo.views.MainFrame;

public class XProcessingUnit extends TriggeredProcessingUnit {

	// gesturespecific values
	private Gesture current; // current gesture

	private Vector<Gesture> trainsequence;

	// State variables
	private boolean learning, analyzing;

	Wiigee wiigee = Wiigee.INSTANCE;
	MainFrame gui;

	public Vector<Gesture> getTrainsequence() {
		return this.trainsequence;
	}

	public Classifier getClassifier() {
		return this.classifier;
	}

	public XProcessingUnit(MainFrame gui) {
		super();
		this.learning = false;
		this.analyzing = false;
		this.current = new Gesture();
		this.trainsequence = new Vector<Gesture>();
		this.gui = gui;
	}

	@Override
	public void accelerationReceived(AccelerationEvent event) {
		if (this.learning || this.analyzing) {
			this.current.add(event); // add event to gesture
		}
	}

	@Override
	public void handleStartEvent(ActionStartEvent event) {
		// TrainButton = record a gesture for learning
		if ((!this.analyzing && !this.learning) && event.isTrainInitEvent()) {
			this.gui.clearTrainingMonitorPanel();
			this.gui.updateTrainingMonitorStatus(Constants.Messages.STATUS_TRAINING_STARTED);
			this.learning = true;
			this.wiigee.setUpdateTrainingMonitorEnabled(true);
		}

		// RecognitionButton = record a gesture for recognition
		if ((!this.analyzing && !this.learning) && event.isRecognitionInitEvent()) {
			this.analyzing = true;
		}

		// CloseGestureButton = starts the training of the model with multiple
		// recognized gestures, contained in trainsequence
		if ((!this.analyzing && !this.learning) && event.isCloseGestureInitEvent()) {

			if (this.trainsequence.size() > 0) {
				this.learning = true;

				GestureModel m = new GestureModel();
				m.train(this.trainsequence);
				// m.print(); // Prints model details after training
				this.gui.updateGestureModelsList(m, this.trainsequence.size());
				this.classifier.addGestureModel(m);

				this.trainsequence = new Vector<Gesture>();
				this.learning = false;
			} else {
				this.gui.updateTrainingMonitorStatus(Constants.Messages.STATUS_TRAINING_NOTHING_TO_DO);
			}
		}
	}

	@Override
	public void handleStopEvent(ActionStopEvent event) {
		if (this.learning) { // button release and state=learning, stops learning
			if (this.current.getCountOfData() > 0) {
				this.gui.updateTrainingMonitorStatus(Constants.Messages.STATUS_FINISHED_RECORDING_TRAINING + this.current.getCountOfData());
				Gesture gesture = new Gesture(this.current);
				this.trainsequence.add(gesture);
				this.current = new Gesture();
				this.learning = false;
			} else {
				this.gui.updateTrainingMonitorStatus(Constants.Messages.STATUS_TRAINING_NO_DATA);
				this.learning = false; // ?
			}
			this.wiigee.setUpdateTrainingMonitorEnabled(false);
			this.gui.updateTrainingCount(this.trainsequence.size());
			this.gui.updateTrainingMonitorStatus("/ " + this.wiigee.getAccelerationReceivedCount() + " " + Constants.Messages.STATUS_ACCELERATION_DATA_RECEIVED, true);
			this.wiigee.resetAccelerationReceivedCount();
		}

		else if (this.analyzing) { // button release and state=analyzing, stops analyzing
			if (this.current.getCountOfData() > 0) {
				Gesture gesture = new Gesture(this.current);

				int recognized = this.classifier.classifyGesture(gesture);
				if (recognized != -1) {
					double recogprob = this.classifier.getLastProbability();
					this.fireGestureEvent(true, recognized, recogprob);
					this.gui.updateGestureRecognitionStatus(Constants.Messages.STATUS_GESTURE_RECOGNIZED_NUM + recognized + " (" + this.gui.getGestureModelDisplayName(recognized) + ") " + Constants.Messages.STATUS_GESTURE_RECOGNIZED_RECOGPROB + " " + recogprob);
				} else {
					this.fireGestureEvent(false, 0, 0.0);
					this.gui.updateGestureRecognitionStatus(Constants.Messages.STATUS_NO_GESTURE_RECOGNIZED);
				}

				this.current = new Gesture();
				this.analyzing = false;
			} else {
				this.gui.updateGestureRecognitionStatus(Constants.Messages.STATUS_RECOGNIZING_NO_DATA);
				this.analyzing = false; // ?
			}
		}
	}
}
